home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 April / EnigmA AMIGA RUN 17 (1997)(G.R. Edizioni)(IT)[!][issue 1997-04][EAR-CD].iso / EARCD / comm / bbs / citsrc6K05.lha / confg.c < prev    next >
C/C++ Source or Header  |  1996-10-26  |  46KB  |  1,844 lines

  1. /*
  2. *           confg.c
  3. *
  4. * Configuration program for Citadel bulletin board system.
  5. */
  6. #define CONFIGURE
  7. #include "ctdl.h"
  8. #include "math.h"
  9. /*
  10. *       History
  11. *
  12. * 85Dec26 HAW  Add CALL-LOG define.
  13. * 85Nov15 HAW  MS-DOS library update.
  14. * 85Oct27 HAW  Kill CERMETEK.
  15. * 85Oct17 HAW  Add paramVers, change bauds to array, searchBaud chg.
  16. * 85Oct16 HAW  Kill CLOCK, add officeStuff.
  17. * 85Aug24 HAW  Add duomessage file, NETDISK specification.
  18. * 85Jul07 HAW  Update so won't go through total recon. on init.
  19. * 85May27 HAW  Start stuffing in auto-networking stuff.
  20. * 85May22 HAW  Start conversion to make log file size sysop selectable.
  21. * 85May11 HAW  Make "Lobby" sysop definable
  22. * 85May06 HAW  Add bail out code.
  23. * 85May05 HAW  Add helpDisk parameter for 3 disk system.
  24. * 85Apr10 HAW  Fix logSort, alphabetize file.
  25. * 85Mar11 HAW  Put all user functions in this file.
  26. * 85Feb18 HAW  Add baud search stuff.
  27. * 85Jan20 HAW  Use MSDOS #define for date stuff.
  28. * 84Sep05 HAW  Isolate strangeness in compiler's library.  See note.
  29. * 84Aug30 HAW  Onwards to MS-DOS!
  30. * 84Apr08 HAW  Update to BDS C 1.50a begun.
  31. * 82Nov20 CrT  Created.
  32. */
  33. /*
  34. *       Contents
  35. *
  36. * dGetWord()    reads a word off disk
  37. * init()      system startup initialization
  38. * main()      main controller
  39. * illegal()   abort bottleneck
  40. * msgInit()   sets up cfg.catChar, catSect etc.
  41. * zapMsgFile()    initialize ctdlmsg.sys
  42. * realZap()   does work of zapMsgFile()
  43. * indexRooms()    build RAM index to ctdlroom.sys
  44. * noteRoom()    enter room into RAM index
  45. * zapRoomFile()   erase & re-initialize ctdlroom.sys
  46. * setSpace()    set default disk and user#
  47. * hash()      hashes a string to an integer
  48. * logInit()   builds the RAM index to CTDLLOG.SYS
  49. * noteLog()   enters a userlog record into RAM index
  50. * sortLog()   sort CTDLLOG by time since last call
  51. * wrapup()    finishes and writes ctdlTabl.sys
  52. * zapLogFile()    erases & re-initializes CTDLLOG.SYS
  53. */
  54. /*
  55. *   Strangenesses   (Hue, Jr., 12Sep84)
  56. * Have discovered that the line:
  57. * sscanf(line, "\"%s\"", str);
  58. * is not parsed the same way by this compiler as it is by BDS;
  59. * this is highly unfortunate and excrable.  So, all porters
  60. * should note that scanf() is not, in any way, "portable."  If
  61. * BDS is "non-standard", then the standard sucks.
  62. */
  63. #define BAUDS "Valid SYSBAUD values: 0=300, 1=1200, 2=2400, 3=4800,\n4=9600, 5=14.4, 6=19.2, 7=38.4, 8=57.6"
  64. struct GenList
  65.   {
  66.   char *GenName;
  67.   int  GenVal;
  68.  
  69.   };
  70. extern FILE *msgfl, *msgfl2;    /* file descriptor for the msg file */
  71. char   *baseRoom;
  72. int   mailCount=0;
  73. char   msgZap =  FALSE,
  74. logZap =  FALSE,
  75. roomZap = FALSE;
  76. char  FirstInit = FALSE;
  77. char  ReInit = FALSE;
  78. static DATA_BLOCK sectBuf;
  79. long FloorSize;
  80. int  DefaultPrefix;
  81. void  Zap_Nodes_Message_Index(void);  /* zap last netted message */
  82.  
  83.  
  84. static char NetParse(char *line, int *offset, char *var, int arg, int SetVal);
  85. extern SListBase Events;    /* event list     */
  86. extern CONFIG    cfg;      /* The configuration variable  */
  87. extern MessageBuffer   msgBuf;    /* The -sole- message buffer  */
  88. extern NetBuffer netBuf;
  89. extern rTable    *roomTab;        /* RAM index of rooms   */
  90. extern aRoom     roomBuf;        /* room buffer     */
  91. extern EVENT     *EventTab;
  92. extern int       thisRoom;        /* room currently in roomBuf  */
  93. extern int       thisNet;
  94. extern LogTable  *logTab;        /* RAM index of pippuls    */
  95. extern logBuffer logBuf;    /* Log buffer of a person       */
  96. extern SListBase Serves;
  97. extern FILE      *logfl;    /* log file descriptor    */
  98. extern FILE      *roomfl;        /* file descriptor for rooms */
  99. extern FILE      *netfl;
  100. extern LogTable  *logTab;        /* RAM index of pippuls    */
  101. extern int       thisLog;        /* entry currently in logBuf */
  102. extern NetTable  *netTab;
  103. void CheckNet( void );
  104. /*
  105. * init()
  106. *
  107. * The master system initialization.
  108. */
  109. void init(int attended)
  110.   {
  111.   extern char   *W_R_ANY;
  112.   extern char   *R_W_ANY;
  113.   extern char   *READ_ANY;
  114.   extern char   *WRITE_ANY;
  115.   unsigned char c;
  116.   SYS_FILE      tempName;
  117.   extern int    errno, _doserrno;
  118.   cfg.sizeLTentry = sizeof(*logTab);
  119.   cfg.BoolFlags.debug       = FALSE;
  120.   cfg.BoolFlags.noChat      = TRUE;
  121.   /* shave-and-a-haircut/two bits pause pattern for ringing sysop: */
  122.   cfg.shave[0]    = 40;
  123.   cfg.shave[1]    = 20;
  124.   cfg.shave[2]    = 20;
  125.   cfg.shave[3]    = 40;
  126.   cfg.shave[4]    = 80;
  127.   cfg.shave[5]    = 40;
  128.   cfg.shave[6]    =250;
  129.   /* initialize input character-translation table:  */
  130.   for (c = 0;  c < '\40';  c++)
  131.     {
  132.     cfg.filter[c] = '\0';    /* control chars -> nulls  */
  133.  
  134.     }
  135.   cfg.filter[1] = 'y';    /* fix from 3.43, carried back to this version */
  136.   cfg.filter[7] = '7';
  137.   for (c='\40'; c < 128;   c++)
  138.     {
  139.     cfg.filter[c] = c;        /* pass printing chars  */
  140.  
  141.     }
  142.   cfg.filter[SPECIAL]     = SPECIAL;
  143.   cfg.filter[CNTRLl]      = CNTRLl;
  144.   cfg.filter[DEL      ]   = BACKSPACE;
  145.   cfg.filter[BACKSPACE]   = BACKSPACE;
  146.   cfg.filter[XOFF     ]   = XOFF     ;
  147.   cfg.filter[XON      ]   = XON      ;
  148.   cfg.filter['\r'     ]   = NEWLINE  ;
  149.   cfg.filter[CNTRLO   ]   = 'N'      ;
  150.   mvToHomeDisk(&cfg.homeArea);
  151.   makeSysName(tempName, "ctdlmsg.sys",  &cfg.msgArea);
  152.   if ((msgfl = fopen(tempName, R_W_ANY)) == NULL)
  153.     {
  154.     if (!attended)illegal("!System must be attended(ctdlmsg.sys) for creation!");
  155.     printf(" %s not found, creating new file. \n", tempName);
  156.     if ((msgfl = fopen(tempName, W_R_ANY)) == NULL)    illegal("?Can't create the message file!");
  157.     printf(" (Be sure to initialize it!)\n");
  158.  
  159.     }
  160.   makeSysName(tempName, "ctdllog.sys", &cfg.logArea);
  161.   /* open userlog file */
  162.   if ((logfl = fopen(tempName, R_W_ANY)) == NULL)
  163.     {
  164.     if (!attended)illegal("!System must be attended(ctdllog.sys) for creation!");
  165.     printf(" %s not found, creating new file. \n", tempName);
  166.     if ((logfl = fopen(tempName, W_R_ANY)) == NULL) illegal("?Can't create log file!");
  167.     printf(" (Be sure to initialize it!)\n");
  168.  
  169.     }
  170.   makeSysName(tempName, "ctdlroom.sys", &cfg.roomArea);
  171.   /* open room file */
  172.   if ((roomfl = fopen(tempName, R_W_ANY)) == NULL)
  173.     {
  174.     if (!attended)illegal("!System must be attended(ctdlroom.sys) for creation!");
  175.     printf(" %s not found, creating new file. \n", tempName);
  176.     if ((roomfl = fopen(tempName, W_R_ANY)) == NULL) illegal("?Can't create room file!");
  177.     printf(" (Be sure to initialize it!)\n");
  178.  
  179.     }
  180.   if (cfg.BoolFlags.netParticipant)
  181.     {
  182.     makeSysName(tempName, "ctdlnet.sys", &cfg.netArea);
  183.     if ((netfl = fopen(tempName, READ_ANY)) == NULL)
  184.       {
  185.       printf(" %s not found, creating new file.\n", tempName);
  186.       if ((netfl = fopen(tempName, WRITE_ANY)) == NULL)illegal("?Can't create the net file!");
  187.  
  188.       }
  189.  
  190.     }
  191.   CheckFloors();
  192.   if (attended || FirstInit)
  193.     {
  194.     char cx;
  195.     printf("\n Erase and initialize log, message and/or room files?");
  196.     cx = simpleGetch();
  197.     if (FirstInit || toUpper(cx)  == 'Y')
  198.       {
  199.       /* each of these has an additional go/no-go interrogation: */
  200.       msgZap  = zapMsgFile();
  201.       roomZap = zapRoomFile();
  202.       logZap  = zapLogFile();
  203.  
  204.       }
  205.  
  206.     }
  207.  
  208.   }
  209. /*
  210. * main()
  211. *
  212. * Main manager for confg.c.
  213. */
  214. int main(int, char **);
  215. int main(int argc, char **argv)
  216.   {
  217.   FILE *fBuf, *pwdfl;
  218.   char line[90], status, *strchr(), *g;
  219.   char onlyParams = FALSE, CleanCalllog;
  220.   char var[90];
  221.   int  arg;
  222.   int  i, offset = 1;
  223.   extern char *READ_TEXT;
  224.   int  SetVal;
  225.   if (argc > 1)
  226.     {
  227.     if (strCmpU(argv[1], "exists") == 0)
  228.       {
  229.       fBuf = fopen("exists", "w");
  230.       fprintf(fBuf, "I exist.");
  231.       fclose(fBuf);
  232.       exit(1);
  233.  
  234.       }
  235.  
  236.     }
  237.   cfg.paramVers = 11;
  238.   printf("%s Configurator (V%d.8) %s\n%s\n\n", VARIANT_NAME,
  239.   cfg.paramVers,VERSION_NAME, COPYRIGHT);
  240.   if (access(LOCKFILE, 0) != -1)
  241.     {
  242.     char cx;
  243.     printf(
  244.     "You are apparently reconfiguring from within Citadel, which is a No No!\n"
  245.     "Do you wish to continue? ");
  246.     cx = simpleGetch();
  247.     if (toUpper(cx) != 'Y')
  248.     exit(7);
  249.     unlink(LOCKFILE);
  250.  
  251.     }
  252.   zero_struct(cfg);
  253.   for (i = 1;  i < argc; i++)
  254.     {
  255.     if (strCmpU(argv[i], "onlyParams") == SAMESTRING )
  256.       onlyParams = TRUE;
  257.     else if (strCmpU(argv[i], "FirstInit") == SAMESTRING)
  258.       FirstInit = TRUE;
  259.     else if (strCmpU(argv[i], "ReInit") == SAMESTRING)
  260.       ReInit = TRUE;
  261.     else if( argv[i][0] == '-' )
  262.       {
  263.       switch (argv[i][1])
  264.         {
  265.         case 'o':   /* Only Parameters */
  266.         case 'O':   onlyParams = TRUE; break;
  267.         case 'F':   /* First Initialization */
  268.         case 'I':
  269.         case 'f':
  270.         case 'i':   FirstInit = TRUE; break;
  271.         case 'r':   /* Re-Initialization */
  272.         case 'R':   ReInit = TRUE; break;
  273.         default:
  274.           fprintf(stderr,"Parameter Error, Assuming ReInit\n");
  275.           ReInit = TRUE;
  276.         };
  277.       }
  278.     else if (!sysArgs(argv[i]))
  279.       ReInit = TRUE;
  280.     }
  281.   cfg.weAre     = CONFIGUR;
  282.   if (!(SetVal = readSysTab(FALSE, FALSE)))
  283.     {
  284.     cfg.sysPassword[0] = 0;
  285.     cfg.MAXLOGTAB = 0;      /* Initialize, just in case   */
  286.     cfg.ConTimeOut = -1;  /* optional parameter */
  287.     if (onlyParams)
  288.       {
  289.       printf("'onlyParams' parameter ignored\n");
  290.       onlyParams = FALSE;
  291.  
  292.       }
  293.  
  294.     }
  295.   else
  296.     {
  297.     if (EventTab != NULL) free(EventTab);
  298.     i = cfg.BoolFlags.noChat;
  299.     zero_struct(cfg.BoolFlags);
  300.     cfg.BoolFlags.noChat = i;
  301.  
  302.     }
  303.   cfg.paramVers = 11;   /* yes, set it twice*   */
  304.   InitBuffers();        /* initializes message buffers */
  305.   initSysSpec();        /* Call implementation specific code  */
  306.   /* these are mostly optional param values */
  307.   cfg.SysopName[0]     = 0;
  308.   cfg.SysopArchive[0]  = 0;
  309.   strCpy(cfg.DomainDisplay, " _ %s");
  310.   cfg.InitColumns      = 40;
  311.   cfg.BoolFlags.IsDoor = FALSE;
  312.   cfg.BoolFlags.NetScanBad = FALSE;
  313.   cfg.EvNumber   = 0;
  314.   cfg.MailHub    = 0;
  315.   cfg.DomainHandlers   = 0;
  316.   KillList(&Serves);
  317.   CleanCalllog   = FALSE;
  318.   cfg.Audit     = 0;
  319.   cfg.BoolFlags.RouteMail  = TRUE;
  320.   cfg.BoolFlags.DL_Default = TRUE;
  321.   cfg.AnonMailLength   = 0;
  322.   cfg.LoginAttempts    = 0;
  323.   zero_array(cfg.DialPrefixes);
  324.   cfg.MailHub   = 0;
  325.   EventTab = NULL;
  326.   if ((fBuf = fopen("ctdlcnfg.sys", READ_TEXT)) == NULL)
  327.     {
  328.     /* ASCII mode   */
  329.     printf("?Can't find ctdlCnfg.sys!\n");
  330.     exit(1);
  331.  
  332.     }
  333.   while (fgets(line, 90, fBuf) != NULL)
  334.     {
  335.     if (line[0] != '#') continue;
  336.     if (sscanf(line, "%s %d ", var, &arg))
  337.       {
  338.       printf("%s", line);
  339.       if (NetParse(line, &offset, var, arg, SetVal))
  340.         {
  341.         continue;
  342.  
  343.         }
  344.       else if (strCmpU(var, "#CRYPTSEED" )    == SAMESTRING)
  345.         {
  346.         cfg.cryptSeed   = arg;
  347.  
  348.         }
  349.       else if (strCmpU(var, "#MESSAGEK"  )    == SAMESTRING)
  350.         {
  351.         cfg.maxMSector  = arg*(1024/MSG_SECT_SIZE);
  352.  
  353.         }
  354.       else if (strCmpU(var, "#LOGINOK"   )    == SAMESTRING)
  355.         {
  356.         cfg.BoolFlags.unlogLoginOk= arg;
  357.  
  358.         }
  359.       else if (strCmpU(var, "#ISDOOR"   )    == SAMESTRING)
  360.         {
  361.         cfg.BoolFlags.IsDoor = TRUE;
  362.  
  363.         }
  364.       else if (strCmpU(var, "#DoorPrivs")     == SAMESTRING)
  365.         {
  366.         cfg.BoolFlags.DoorDft     = arg;
  367.  
  368.         }
  369.       else if (strCmpU(var, "#FILE-PRIV-DEFAULT")     == SAMESTRING)
  370.         {
  371.         cfg.BoolFlags.DL_Default     = arg;
  372.  
  373.         }
  374.       else if (strCmpU(var, "#ENTEROK"   )    == SAMESTRING)
  375.         {
  376.         cfg.BoolFlags.unlogEnterOk= arg;
  377.  
  378.         }
  379.       else if (strCmpU(var, "#READOK"    )    == SAMESTRING)
  380.         {
  381.         cfg.BoolFlags.unlogReadOk = arg;
  382.  
  383.         }
  384.       else if (strCmpU(var, "#ROOMOK"    )    == SAMESTRING)
  385.         {
  386.         cfg.BoolFlags.nonAideRoomOk=arg;
  387.  
  388.         }
  389.       else if (strCmpU(var, "#ALLMAIL"   )    == SAMESTRING)
  390.         {
  391.         cfg.BoolFlags.noMail      = !arg;
  392.  
  393.         }
  394.       else if (strCmpU(var, "#UNLOGGED-WIDTH") == SAMESTRING)
  395.         {
  396.         cfg.InitColumns = arg;
  397.  
  398.         }
  399.       else if (strCmpU(var, "#LOGIN-ATTEMPTS") == SAMESTRING)
  400.         {
  401.         cfg.LoginAttempts = arg;
  402.  
  403.         }
  404.       else if (strCmpU(var, "#ANON-MAIL-LENGTH") == SAMESTRING)
  405.         {
  406.         cfg.AnonMailLength = arg;
  407.  
  408.         }
  409.       else if (strCmpU(var, "#CLEAN-CALLLOG") == SAMESTRING)
  410.         {
  411.         CleanCalllog = TRUE;
  412.  
  413.         }
  414.       else if (strCmpU(var, "#ANONYMOUS-SESSIONS") == SAMESTRING)
  415.         {
  416.         cfg.BoolFlags.AnonSessions = TRUE;
  417.  
  418.         }
  419.       else if (strCmpU(var, "#MIRRORMSG" )    == SAMESTRING)
  420.         {
  421.         cfg.BoolFlags.mirror = arg;
  422.  
  423.         }
  424.       else if (strCmpU(var, "#LOGSIZE"   )    == SAMESTRING)
  425.         {
  426.         if (SetVal)
  427.           {
  428.           if (cfg.MAXLOGTAB != arg)
  429.           illegal(
  430.           "LOGSIZE parameter does not equal old value!");
  431.  
  432.           }
  433.         else
  434.           {
  435.           cfg.MAXLOGTAB   = arg;
  436.           logTab = (LogTable *)
  437.           GetDynamic(sizeof(*logTab) * arg);
  438.  
  439.           }
  440.  
  441.         }
  442.       else if (strCmpU(var, "#MAXROOMS"  )    == SAMESTRING)
  443.         {
  444.         if (SetVal)
  445.           {
  446.           if (MAXROOMS != arg)
  447.           illegal(
  448.           "MAXROOMS parameter does not equal old value!");
  449.  
  450.           }
  451.         else
  452.           {
  453.           MAXROOMS = arg;
  454.           if (MAXROOMS <= 3)
  455.           illegal("MAXROOMS must be greater than 3!");
  456.           roomTab = (rTable *)
  457.           GetDynamic(MAXROOMS * sizeof *roomTab);
  458.  
  459.           }
  460.  
  461.         }
  462.       else if (strCmpU(var, "#MSG-SLOTS" )    == SAMESTRING)
  463.         {
  464.         if (SetVal)
  465.           {
  466.           if (MSGSPERRM != arg)
  467.           illegal(
  468.           "MSGSPERRM parameter does not equal old value!");
  469.  
  470.           }
  471.         else
  472.           {
  473.           MSGSPERRM = arg;
  474.  
  475.           }
  476.  
  477.         }
  478.       else if (strCmpU(var, "#MAIL-SLOTS")    == SAMESTRING)
  479.         {
  480.         if (SetVal)
  481.           {
  482.           if (MAILSLOTS != arg)
  483.           illegal(
  484.           "MAILSLOTS parameter does not equal old value!");
  485.  
  486.           }
  487.         else
  488.           {
  489.           MAILSLOTS = arg;
  490.  
  491.           }
  492.  
  493.         }
  494.       else if (strCmpU(var, "#AIDESEEALL")    == SAMESTRING)
  495.         {
  496.         cfg.BoolFlags.aideSeeAll = arg;
  497.  
  498.         }
  499.       else if (strCmpU(var, "#CONSOLE-TIMEOUT")    == SAMESTRING)
  500.         {
  501.         cfg.ConTimeOut = arg;
  502.  
  503.         }
  504.       else if (strCmpU(var, "#SYSBAUD"   )    == SAMESTRING)
  505.         {
  506.         cfg.sysBaud   = arg;
  507.         if (arg > 8 || arg < 0)
  508.           {
  509.           illegal(BAUDS);
  510.  
  511.           }
  512.  
  513.         }
  514.       else if (strCmpU(var, "#event"    ) == SAMESTRING)
  515.         {
  516.         offset = EatEvent(line, offset);
  517.  
  518.         }
  519.       else if (strCmpU(var, "#nodeTitle") == SAMESTRING)
  520.         {
  521.         readString(line, &cfg.codeBuf[offset], TRUE);
  522.         cfg.nodeTitle = offset;
  523.         while (cfg.codeBuf[offset])
  524.         offset++;
  525.         offset++;
  526.  
  527.         }
  528.       else if (strCmpU(var, "#sysPassword") == SAMESTRING)
  529.         {
  530.         readString(line, cfg.sysPassword, FALSE);
  531.         if ((pwdfl = fopen(cfg.sysPassword, READ_TEXT)) == NULL)
  532.           {
  533.           printf("\nNo system password file found\n");
  534.           cfg.sysPassword[0] = 0;
  535.  
  536.           }
  537.         else
  538.           {
  539.           fgets(cfg.sysPassword, 199, pwdfl);
  540.           /*  cfg.sysPassword[strLen(cfg.sysPassword) - 1] = 0;*/
  541.           while ((g = strchr(cfg.sysPassword, '\n')) != NULL)
  542.           *g = 0;
  543.           if (strLen(cfg.sysPassword) < 15)
  544.             {
  545.             printf("\nSystem password is too short -- ignored\n");
  546.             cfg.sysPassword[0] = 0;
  547.  
  548.             }
  549.           fclose(pwdfl);
  550.  
  551.           }
  552.  
  553.         }
  554.       else if (strCmpU(var, "#sysopName") == SAMESTRING)
  555.         {
  556.         readString(line, msgBuf.mbtext, FALSE);
  557.         if (strLen(msgBuf.mbtext) > 19)
  558.         illegal("SysopName too long; must be less than 20");
  559.         strCpy(cfg.SysopName, msgBuf.mbtext);
  560.  
  561.         }
  562.       else if (strCmpU(var, "#SYSOP-ARCHIVE") == SAMESTRING)
  563.         {
  564.         readString(line, msgBuf.mbtext, FALSE);
  565.         if (strLen(msgBuf.mbtext) > sizeof cfg.SysopArchive)
  566.           {
  567.           sprintf(msgBuf.mbtext, "SysopName too long; must be less than %d", sizeof cfg.SysopArchive);
  568.           illegal(msgBuf.mbtext);
  569.  
  570.           }
  571.         strCpy(cfg.SysopArchive, msgBuf.mbtext);
  572.  
  573.         }
  574.       else if (strCmpU(var, "#baseRoom") == SAMESTRING)
  575.         {
  576.         readString(line, &cfg.codeBuf[offset], TRUE);
  577.         if (strLen(&cfg.codeBuf[offset]) > 19)
  578.         illegal("baseRoom too long; must be less than 20");
  579.         cfg.bRoom = offset;
  580.         baseRoom = &cfg.codeBuf[offset];
  581.         while (cfg.codeBuf[offset])
  582.         offset++;
  583.         offset++;
  584.  
  585.         }
  586.       else if (strCmpU(var, "#MainFloor") == SAMESTRING)
  587.         {
  588.         readString(line, &cfg.codeBuf[offset], TRUE);
  589.         if (strLen(&cfg.codeBuf[offset]) > 19)
  590.         illegal("#MainFloor too long; must be less than 20");
  591.         cfg.MainFloor = offset;
  592.         while (cfg.codeBuf[offset])
  593.         offset++;
  594.         offset++;
  595.  
  596.         }
  597.       else if (strCmpU(var, "#alldone") == SAMESTRING)
  598.         {
  599.         break;
  600.  
  601.         }
  602.       else
  603.         {
  604.         offset = sysSpecs(line, offset, &status, fBuf);
  605.         if (!status)
  606.         printf("? -- no variable '%s' known! -- ignored.\n", var);
  607.  
  608.         }
  609.  
  610.       }
  611.  
  612.     }
  613.   for (i = 0; i <= B_7; i++)
  614.   if (cfg.DialPrefixes[i] == 0)
  615.     {
  616.     cfg.DialPrefixes[i] = DefaultPrefix;
  617.  
  618.     }
  619.   if (cfg.Audit == 1)
  620.   if (CleanCalllog) cfg.Audit = 2;
  621.   initLogBuf(&logBuf);
  622.   initRoomBuf(&roomBuf);
  623.   initNetBuf(&netBuf);
  624.   if (!SysDepIntegrity(&offset))  exit(100);
  625.   RunList(&Events, EvIsDoor);
  626.   printf("offset=%d\n", offset);
  627.   if (offset < MAXCODE)
  628.     {
  629.     if (!onlyParams) init(!ReInit);
  630.     else
  631.       {
  632.       CheckFloors();
  633.       if (cfg.BoolFlags.netParticipant)
  634.       CheckNet();
  635.  
  636.       }
  637.     wrapup(onlyParams);
  638.  
  639.     }
  640.   else
  641.     {
  642.     illegal(
  643.     "\7codeBuf[] overflow! Recompile with larger MAXCODE or reduce ctdlCnfg.sys\7"
  644.     );
  645.  
  646.     }
  647.   return 0;
  648.  
  649.   }
  650. /*
  651. * readString()
  652. *
  653. * This function reads a '#<id> "<value>"  since scanf can't.
  654. */
  655. void readString(char *source, char *destination, char doProc)
  656.   {
  657.   char string[300], last = 0;
  658.   int  i, j;
  659.   for (i = 0; source[i] != '"' && source[i]; i++)
  660.   ;
  661.   if (!source[i])
  662.     {
  663.     sPrintf(string, "Couldn't find beginning \" in -%s-", source);
  664.     illegal(string);
  665.  
  666.     }
  667.   for (j = 0, i++; source[i] &&
  668.   (source[i] != '"' || (doProc && last == '\\'));
  669.   i++, j++)
  670.     {
  671.     string[j] = source[i];
  672.     last = source[i];
  673.  
  674.     }
  675.   if (!source[i])
  676.     {
  677.     sPrintf(string, "Couldn't find ending \" in -%s-", source);
  678.     illegal(string);
  679.  
  680.     }
  681.   string[j] = '\0';
  682.   strCpy(destination, string);
  683.   if (doProc) xlatfmt(destination);
  684.  
  685.   }
  686. /*
  687. * isoctal() * xlatfmt()
  688. *
  689. * contributed by Dale Schumacher, allow embedding of formatting info a la'
  690. * "C" style: \n, \t, etc....
  691. */
  692. char isoctal( int c )
  693.   {
  694.   return  (char)(( c >= '0' ) && ( c <= '7' ));
  695.  
  696.   }
  697. void xlatfmt( char *s )
  698.   {
  699.   register char *p, *q;
  700.   register int i;
  701.   for( p=q=s; *q; ++q )
  702.     {
  703.     if ( *q == '\\' )
  704.     switch( *++q )
  705.       {
  706.       case 'n' :
  707.       *p++ = '\n';
  708.       break;
  709.       case 't' :
  710.       *p++ = '\t';
  711.       break;
  712.       case 'r' :
  713.       *p++ = '\r';
  714.       break;
  715.       case 'f' :
  716.       *p++ = '\f';
  717.       break;
  718.       default :
  719.       if ( isoctal( *q ))
  720.         {
  721.         i = (( *q++ ) - '0' );
  722.         if ( isoctal( *q ))
  723.           {
  724.           i <<= 3;
  725.           i += (( *q++ ) - '0' );
  726.           if ( isoctal( *q ))
  727.             {
  728.             i <<= 3;
  729.             i += (*q -'0');
  730.  
  731.             }
  732.           else
  733.           --q;
  734.  
  735.           }
  736.         else
  737.         --q;
  738.         *p++ = 0xFF & ((char) i);
  739.  
  740.         }
  741.       else
  742.       *p++ = *q;
  743.       break;
  744.  
  745.       }
  746.     else
  747.     *p++ = *q;
  748.  
  749.     }
  750.   *p = '\0';
  751.  
  752.   }
  753. /*
  754. * illegal()
  755. *
  756. * This will print out configure error message and aborts.
  757. */
  758. void illegal(char *errorstring)
  759.   {
  760.   printf("\007\nERROR IN CONFIGURATION:\n%s\nABORTING", errorstring);
  761.   exit(100);
  762.  
  763.   }
  764. /*
  765. * dGetWord()
  766. *
  767. * This fetches one word from current message, off disk, returns TRUE if more
  768. * words follow, else FALSE.
  769. */
  770. char dGetWord(char *dest, int lim)
  771.   {
  772.   char c;
  773.   --lim;      /* play it safe */
  774.   /* pick up any leading blanks: */
  775.   for (c = getMsgChar();   c == ' '  &&  c && lim;   c = getMsgChar())
  776.     {
  777.     if (lim)
  778.       {
  779.       *dest++ = c;   lim--;
  780.  
  781.       }
  782.  
  783.     }
  784.   /* step through word: */
  785.   for (   ;  c != ' ' && c && lim;   c = getMsgChar())
  786.     {
  787.     if (lim)
  788.       {
  789.       *dest++ = c;   lim--;
  790.  
  791.       }
  792.  
  793.     }
  794.   /* trailing blanks: */
  795.   for (   ;   c == ' ' && c && lim;   c = getMsgChar())
  796.     {
  797.     if (lim)
  798.       {
  799.       *dest++ = c;   lim--;
  800.  
  801.       }
  802.  
  803.     }
  804.   if (c)  unGetMsgChar(c);    /* took one too many    */
  805.   *dest = '\0';        /* tie off string       */
  806.   return  c;
  807.  
  808.   }
  809. /*
  810. * msgInit()
  811. *
  812. * This sets up lowId, highId, cfg.catSector and cfg.catChar, by scanning over
  813. * ctdlmsg.sys.
  814. */
  815. void msgInit()
  816.   {
  817.   MSG_NUMBER first, here;
  818.   CheckPoint Cpt;
  819.   FILE *fd;
  820.   extern struct mBuf mFile1;
  821.   if ((fd = fopen(CHECKPT, READ_ANY)) != NULL)
  822.     {
  823.     fread(&Cpt, sizeof Cpt, 1, fd);
  824.     fclose(fd);
  825.     if (findMessage(Cpt.loc, Cpt.ltnewest, TRUE))
  826.       {
  827.       do
  828.         {
  829.         printf("message# %s\r", msgBuf.mbId);
  830.         while (dGetWord(msgBuf.mbtext, MAXTEXT));
  831.         cfg.catSector   = mFile1.thisSector;
  832.         cfg.catChar     = mFile1.thisChar;
  833.         cfg.newest      = atol(msgBuf.mbId);
  834.         getMessage(getMsgChar, FALSE, FALSE, TRUE);
  835.  
  836.         }
  837.       while (atol(msgBuf.mbId) >= Cpt.ltnewest);
  838.       cfg.oldest = atol(msgBuf.mbId);
  839.       printf("\n\noldest=%lu\n", cfg.oldest);
  840.       printf("newest=%lu\n", cfg.newest);
  841.       return;
  842.  
  843.       }
  844.  
  845.     }
  846.   startAt(msgfl, &mFile1, 0, 0);
  847.   getMessage(getMsgChar, FALSE, FALSE, TRUE);
  848.   /* get the ID# */
  849.   first = atol(msgBuf.mbId);
  850.   printf("message# %lu\n", first);
  851.   cfg.newest = cfg.oldest = first;
  852.   cfg.catSector   = mFile1.thisSector;
  853.   cfg.catChar     = mFile1.thisChar;
  854.   for (getMessage(getMsgChar, FALSE, FALSE, TRUE);
  855.   here = atol(msgBuf.mbId), here != first;
  856.   getMessage(getMsgChar, FALSE, FALSE, TRUE))
  857.     {
  858.     printf("message# %lu\r", here);
  859.     if (strCmpU("Mail", msgBuf.mbroom) == 0) mailCount++;
  860.     /* find highest and lowest message IDs: */
  861.     if (here < cfg.oldest && here != 0l)
  862.       {
  863.       cfg.oldest = here;
  864.  
  865.       }
  866.     if (here > cfg.newest)
  867.       {
  868.       cfg.newest = here;
  869.       /* read rest of message in and remember where it ends,  */
  870.       /* in case it turns out to be the last message    */
  871.       /* in which case, that's where to start writing next message*/
  872.       while (dGetWord(msgBuf.mbtext, MAXTEXT));
  873.       cfg.catSector   = mFile1.thisSector;
  874.       cfg.catChar     = mFile1.thisChar;
  875.  
  876.       }
  877.  
  878.     }
  879.   printf("\n\noldest=%lu\n", cfg.oldest);
  880.   printf("newest=%lu\n", cfg.newest);
  881.  
  882.   }
  883. /*
  884. * zapMsgFile()
  885. *
  886. * This function initializes ctdlmsg.sys.
  887. */
  888. char zapMsgFile()
  889.   {
  890.   extern char *W_R_ANY;
  891.   char cx, fn[80];
  892.   if (!FirstInit)
  893.     {
  894.     printf("\nDestroy all current messages? ");
  895.     cx = simpleGetch();
  896.     if (toUpper(cx) != 'Y')   return FALSE;
  897.  
  898.     }
  899.   if (cfg.BoolFlags.mirror) printf("Creating primary message file.\n");
  900.   if( realZap() )
  901.     {
  902.     if (cfg.BoolFlags.mirror)
  903.       {
  904.       fclose(msgfl);
  905.       makeSysName(fn, "ctdlmsg.sys", &cfg.msg2Area);
  906.       if ((msgfl = fopen(fn, W_R_ANY)) == NULL)
  907.       illegal("?Can't create the secondary message file!");
  908.       printf("Creating secondary message file.\n");
  909.       realZap();
  910.       };
  911.     };
  912.   return TRUE;
  913.  
  914.   }
  915. /*
  916. * realZap()
  917. *
  918. * This does the work of zapMsgFile.
  919. */
  920. char realZap()
  921.   {
  922.   int   i;
  923.   unsigned long sect;
  924.   /* put null message in first sector... */
  925.   sectBuf[0]  = 0xFF; /*   \        */
  926.   sectBuf[1]  =  '1'; /*    >  Message ID "1" MS-DOS style  */
  927.   sectBuf[2]  = '\0'; /*   /        */
  928.   sectBuf[3]  =  'M'; /*   \    Null messsage        */
  929.   sectBuf[4]  = '\0'; /*   /        */
  930.   cfg.newest = cfg.oldest = 1l;
  931.   cfg.catSector   = 0;
  932.   cfg.catChar     = 5;
  933.   for (i=5;  i<MSG_SECT_SIZE;  i++) sectBuf[i] = 0;
  934.   crypte(sectBuf, MSG_SECT_SIZE, 0);       /* encrypt      */
  935.   if (fwrite(sectBuf, MSG_SECT_SIZE, 1, msgfl) != 1)
  936.     {
  937.     printf("zapMsgFil: write failed\n");
  938.     return FALSE;
  939.     }
  940.   crypte(sectBuf, MSG_SECT_SIZE, 0);       /* decrypt      */
  941.   sectBuf[0] = 0;
  942.   crypte(sectBuf, MSG_SECT_SIZE, 0);       /* encrypt      */
  943.   printf("\n%d sectors to be cleared\n", cfg.maxMSector);
  944.   for (sect = 1l;  sect < cfg.maxMSector;  sect++)
  945.     {
  946.     printf("%07.7lu\r", sect);
  947.     if (fwrite(sectBuf, MSG_SECT_SIZE, 1, msgfl) != 1)
  948.       {
  949.       printf("zapMsgFil: write failed\n");
  950.       return FALSE;
  951.       }
  952.  
  953.     }
  954.   Zap_Nodes_Message_Index();               /* zap last netted message */
  955.   crypte(sectBuf, MSG_SECT_SIZE, 0);       /* decrypt      */
  956.   return TRUE;
  957.  
  958.   }
  959. /*
  960. * indexRooms()
  961. *
  962. * This will build a RAM index to CTDLROOM.SYS, displays stats.
  963. */
  964. void indexRooms()
  965.   {
  966.   int shared_room_count;
  967.   int  goodRoom, m, roomCount, slot, WriteIt;
  968.   zero_struct(roomBuf.rbflags);
  969.   zero_struct(roomBuf.rbArea);
  970.   roomBuf.rbgen = 0;
  971.   roomBuf.rbname[0] = 0;
  972.   roomBuf.rbShareType = 0;
  973.   shared_room_count = 0;
  974.   for (m = 0; m < MSGSPERRM; m++)
  975.     {
  976.     roomBuf.msg[m].rbmsgNo = 0l;
  977.     roomBuf.msg[m].rbmsgLoc = 0;
  978.  
  979.     }
  980.   strCpy(roomBuf.rbname, "Mail");
  981.   roomBuf.rbflags.PUBLIC =
  982.   roomBuf.rbflags.PERMROOM =
  983.   roomBuf.rbflags.INUSE = TRUE;
  984.   putRoom(MAILROOM);
  985.   roomCount = 0;
  986.   for (slot = 0;  slot < MAXROOMS;  slot++)
  987.     {
  988.     getRoom(slot);
  989.     printf("Checking room #%3d: ", slot);
  990.     WriteIt = FALSE;
  991.     if (roomBuf.rbflags.INUSE == 1)
  992.       {
  993.       WriteIt = TRUE;
  994.       roomBuf.rbflags.INUSE = 0;    /* clear "inUse" flag */
  995.       if (roomBuf.rbFlIndex >= (int) FloorSize)
  996.       roomBuf.rbFlIndex = 0;
  997.       for (m = 0, goodRoom = FALSE; m < MSGSPERRM && !goodRoom; m++)
  998.         {
  999.         if (roomBuf.msg[m].rbmsgNo > cfg.oldest)
  1000.           {
  1001.           goodRoom    = TRUE;
  1002.  
  1003.           }
  1004.  
  1005.         }
  1006.       if (goodRoom   || roomBuf.rbflags.PERMROOM == 1)
  1007.         {
  1008.         roomBuf.rbflags.INUSE = 1;
  1009.  
  1010.         }
  1011.       if (roomBuf.rbflags.INUSE == 1)
  1012.         {
  1013.         if (slot == 0)         /* Ugly kludge */
  1014.         strCpy(roomBuf.rbname, baseRoom);
  1015.         roomCount++;
  1016.  
  1017.         }
  1018.       else
  1019.         {
  1020.         zero_struct(roomBuf.rbflags);
  1021.  
  1022.         }
  1023.       }
  1024.       else
  1025.         {
  1026.         noteRoom();
  1027.  
  1028.       }
  1029.     printf("%-25s\r",
  1030.     (roomBuf.rbflags.INUSE == 1) ? roomBuf.rbname : "<not in use>");
  1031.     if (WriteIt)
  1032.       {
  1033.       if (roomBuf.rbflags.INUSE && roomBuf.rbflags.SHARED)
  1034.         {
  1035.         shared_room_count++;
  1036.         roomTab[slot].rtlastNet = findHighestNative();
  1037.         }
  1038.       else roomTab[slot].rtlastNet = 0l;
  1039.       noteRoom();
  1040.       putRoom(slot);
  1041.  
  1042.       }
  1043.  
  1044.     }
  1045.   if( SHARED_ROOMS < shared_room_count )
  1046.     {
  1047.     fprintf(stderr,"***Serious Error***\n");
  1048.     fprintf(stderr," You have #SHARED-ROOMS %d in the ctdlcnfg.sys\n",SHARED_ROOMS);
  1049.     fprintf(stderr," There are %d rooms marked shared\n",shared_room_count);
  1050.     fprintf(stderr," Immediately, run DATACHNG and increase your number of shared rooms above %d\n",SHARED_ROOMS);
  1051.     fprintf(stderr," You might trash your system if you don't\n");
  1052.     illegal("Fatal Error");
  1053.     };
  1054.   printf("\n %d of %d rooms in use\n", roomCount, MAXROOMS);
  1055.  
  1056.   }
  1057. /*
  1058. * findHighestNative()
  1059. *
  1060. * This finds the highest native message in a room.
  1061. */
  1062. MSG_NUMBER findHighestNative()
  1063.   {
  1064.   int rover;
  1065.   MSG_NUMBER ourHighest;
  1066.   theMessages *temp;
  1067.   temp = (theMessages *) GetDynamic(MSG_BULK);
  1068.   copy_ptr(roomBuf.msg, temp, MSGSPERRM);
  1069.   qsort(temp, MSGSPERRM, sizeof temp[0], msgSort);
  1070.   ourHighest = 0l;
  1071.   for (rover = 0; rover < MSGSPERRM; rover++)
  1072.     {
  1073.     if (temp[rover].rbmsgNo != 0l &&
  1074.     temp[rover].rbmsgNo >= cfg.oldest &&
  1075.     temp[rover].rbmsgNo <= cfg.newest &&
  1076.     cfindMessage(temp[rover].rbmsgLoc, temp[rover].rbmsgNo))
  1077.       {
  1078.       if (strCmpU(msgBuf.mbaddr, R_SH_MARK) == SAMESTRING ||
  1079.       strCmpU(msgBuf.mbaddr, NON_LOC_NET) == SAMESTRING)
  1080.         {
  1081.         ourHighest = temp[rover].rbmsgNo;
  1082.         break;
  1083.  
  1084.         }
  1085.  
  1086.       }
  1087.  
  1088.     }
  1089.   free(temp);
  1090.   return ourHighest;
  1091.  
  1092.   }
  1093. /*
  1094. * msgSort()
  1095. *
  1096. * This function sorts messages by their native msg id.
  1097. */
  1098. int msgSort(theMessages *s1, theMessages *s2)
  1099.   {
  1100.   if (s1->rbmsgNo < s2->rbmsgNo) return 1;
  1101.   if (s1->rbmsgNo > s2->rbmsgNo) return -1;
  1102.   return 0;
  1103.  
  1104.   }
  1105. /*
  1106. * noteRoom()
  1107. *
  1108. * This function will enter room into RAM index array.
  1109. */
  1110. void noteRoom()
  1111.   {
  1112.   int   i;
  1113.   MSG_NUMBER last;
  1114.   last = 0l;
  1115.   for (i = 0;  i < MSGSPERRM;  i++)
  1116.     {
  1117.     if (roomBuf.msg[i].rbmsgNo > cfg.newest)
  1118.       {
  1119.       roomBuf.msg[i].rbmsgNo = 0l;
  1120.  
  1121.       }
  1122.     if (roomBuf.msg[i].rbmsgNo > last)
  1123.       {
  1124.       last = roomBuf.msg[i].rbmsgNo;
  1125.  
  1126.       }
  1127.  
  1128.     }
  1129.   roomTab[thisRoom].rtlastMessage = last     ;
  1130.   roomTab[thisRoom].rtShareType   = roomBuf.rbShareType;
  1131.   strCpy(roomTab[thisRoom].rtname, roomBuf.rbname) ;
  1132.   roomTab[thisRoom].rtgen     = roomBuf.rbgen  ;
  1133.   roomTab[thisRoom].rtFlIndex = roomBuf.rbFlIndex;
  1134.   copy_struct(roomBuf.rbflags, roomTab[thisRoom].rtflags);
  1135.  
  1136.   }
  1137. /*
  1138. * zapRoomFile()
  1139. *
  1140. * This function erases and re-initializes CTDLROOM.SYS.
  1141. */
  1142. char zapRoomFile()
  1143.   {
  1144.   int i;
  1145.   char cx;
  1146.   if (!FirstInit)
  1147.     {
  1148.     printf("\nWipe room file? ");
  1149.     cx = simpleGetch();
  1150.     if (toUpper(cx) != 'Y') return FALSE;
  1151.     printf("\n");
  1152.  
  1153.     }
  1154.   zero_struct(roomBuf.rbflags);
  1155.   roomBuf.rbgen     = 0;
  1156.   roomBuf.rbname[0] = 0;   /* unnecessary -- but I like it...  */
  1157.   for (i = 0;  i < MSGSPERRM;  i++)
  1158.     {
  1159.     roomBuf.msg[i].rbmsgNo =  0l;
  1160.     roomBuf.msg[i].rbmsgLoc = 0 ;
  1161.  
  1162.     }
  1163.   printf("maxrooms=%d\n", MAXROOMS);
  1164.   for (thisRoom = 0;  thisRoom < MAXROOMS;  thisRoom++)
  1165.     {
  1166.     printf("clearing room %d\r", thisRoom);
  1167.     RoomSys(thisRoom);
  1168.     putRoom(thisRoom);
  1169.     noteRoom();
  1170.  
  1171.     }
  1172.   printf("\n");
  1173.   /* Lobby> always exists -- guarantees us a place to stand! */
  1174.   thisRoom      = 0      ;
  1175.   strCpy(roomBuf.rbname, baseRoom)    ;
  1176.   roomBuf.rbflags.PERMROOM = TRUE;
  1177.   roomBuf.rbflags.PUBLIC   = TRUE;
  1178.   roomBuf.rbflags.INUSE    = TRUE;
  1179.   RoomSys(0);
  1180.   putRoom(LOBBY);
  1181.   noteRoom();
  1182.   /* Mail> is also permanent...       */
  1183.   thisRoom      = MAILROOM      ;
  1184.   strCpy(roomBuf.rbname, "Mail")      ;
  1185.   RoomSys(1);
  1186.   /* Don't bother to copy flags, they remain the same (right?)    */
  1187.   putRoom(MAILROOM);
  1188.   noteRoom();
  1189.   /* Aide> also...    */
  1190.   thisRoom      = AIDEROOM      ;
  1191.   strCpy(roomBuf.rbname, "Aide")      ;
  1192.   roomBuf.rbflags.PERMROOM = TRUE;
  1193.   roomBuf.rbflags.PUBLIC   = FALSE;
  1194.   roomBuf.rbflags.INUSE    = TRUE;
  1195.   RoomSys(2);
  1196.   putRoom(AIDEROOM);
  1197.   noteRoom();
  1198.   return TRUE;
  1199.  
  1200.   }
  1201. /*
  1202. * logInit()
  1203. *
  1204. * This function indexes ctdllog.sys.
  1205. */
  1206. void logInit()
  1207.   {
  1208.   int i;
  1209.   int count = 0;
  1210.   #ifdef IS_RIGHT
  1211.   if (rewind(logfl) != 0) illegal("Rewinding logfl failed!");
  1212.   #else
  1213.   rewind(logfl);
  1214.   #endif
  1215.   /* clear logTab */
  1216.   for (i = 0; i < cfg.MAXLOGTAB; i++) logTab[i].ltnewest = 0l;
  1217.   /* load logTab: */
  1218.   for (thisLog = 0;  thisLog < cfg.MAXLOGTAB;  thisLog++)
  1219.     {
  1220.     printf("log #%04d", thisLog);
  1221.     getLog(&logBuf, thisLog);
  1222.     /* count valid entries:      */
  1223.     if (logBuf.lbflags.L_INUSE == 1)
  1224.       {
  1225.       count++;
  1226.       printf("%-25s \r", logBuf.lbname);
  1227.  
  1228.       }
  1229.     else printf("-25s% \r","<not in use>");
  1230.     /* copy relevant info into index:   */
  1231.     logTab[thisLog].ltnewest = logBuf.lbvisit[0];
  1232.     logTab[thisLog].ltlogSlot= thisLog;
  1233.     if (logBuf.lbflags.L_INUSE == 1)
  1234.       {
  1235.       logTab[thisLog].ltnmhash = hash(logBuf.lbname);
  1236.       logTab[thisLog].ltpwhash = hash(logBuf.lbpw  );
  1237.       logTab[thisLog].ltpermanent = logBuf.lbflags.PERMANENT;
  1238.  
  1239.       }
  1240.     else
  1241.       {
  1242.       logTab[thisLog].ltnmhash = 0;
  1243.       logTab[thisLog].ltpwhash = 0;
  1244.  
  1245.       }
  1246.  
  1247.     }
  1248.   printf("\n logInit--%d valid log entries\n", count);
  1249.   printf("sort Log...\n");
  1250.   qsort(logTab, cfg.MAXLOGTAB, cfg.sizeLTentry, logSort);
  1251.  
  1252.   }
  1253. /*
  1254. * logSort()
  1255. *
  1256. * This function Sorts 2 entries in logTab.
  1257. */
  1258. int logSort(LogTable *s1, LogTable *s2)
  1259.   {
  1260.   if (s1->ltnmhash == 0 && s2->ltnmhash == 0)  return 0;
  1261.   if (s1->ltnmhash == 0 && s2->ltnmhash != 0)  return 1;
  1262.   if (s1->ltnmhash != 0 && s2->ltnmhash == 0)  return -1;
  1263.   if (s1->ltnewest < s2->ltnewest)  return 1;
  1264.   if (s1->ltnewest > s2->ltnewest)  return -1;
  1265.   return 0;
  1266.  
  1267.   }
  1268. /*
  1269. * noteLog()
  1270. *
  1271. * This notes a logTab entry in RAM buffer in master index.
  1272. */
  1273. void noteLog()
  1274.   {
  1275.   int i, slot;
  1276.   /* figure out who it belongs between: */
  1277.   for (i = 0;  logTab[i].ltnewest > logBuf.lbvisit[0];  i++);
  1278.   /* note location and open it up:  */
  1279.   slot = i;
  1280.   slideLTab(slot, cfg.MAXLOGTAB-1);
  1281.   /* insert new record */
  1282.   logTab[slot].ltnewest       = logBuf.lbvisit[0]  ;
  1283.   logTab[slot].ltlogSlot      = thisLog     ;
  1284.   logTab[slot].ltpwhash       = hash(logBuf.lbpw)  ;
  1285.   logTab[slot].ltnmhash       = hash(logBuf.lbname);
  1286.  
  1287.   }
  1288. /*
  1289. * slideLTab()
  1290. *
  1291. * This function slides bottom N slots in logTab down.  For sorting.
  1292. */
  1293. void slideLTab(int slot, int last)
  1294.   {
  1295.   int i;
  1296.   /* open slot up: (movmem isn't guaranteed on overlaps) */
  1297.   for (i = last - 1;  i >= slot;  i--)
  1298.     {
  1299.     movmem(&logTab[i], &logTab[i + 1], cfg.sizeLTentry);
  1300.  
  1301.     }
  1302.  
  1303.   }
  1304. /*
  1305. * wrapup()
  1306. *
  1307. * This finishes up and writes ctdlTabl.sys out, finally.
  1308. */
  1309. void wrapup(char onlyParams)
  1310.   {
  1311.   printf("\ncreating ctdlTabl.sys table\n");
  1312.   if (!onlyParams)
  1313.     {
  1314.     if (!msgZap)  msgInit();
  1315.     if (!roomZap) indexRooms();
  1316.     cfg.weAre = CITADEL;
  1317.     if (!logZap)  logInit();
  1318.     netInit();
  1319.     if (mailCount)
  1320.     printf("%d of the messages were Mail\n", mailCount);
  1321.  
  1322.     }
  1323.   EventTab = (EVENT *) GetDynamic(cfg.EvNumber * sizeof *EventTab);
  1324.   if (!FinalSystemCheck(onlyParams)) exit(2);
  1325.   if (!onlyParams)
  1326.     {
  1327.     if (cfg.BoolFlags.netParticipant)
  1328.     fclose(netfl);
  1329.     fclose(roomfl);
  1330.     fclose(msgfl);
  1331.     fclose(logfl);
  1332.  
  1333.     }
  1334.   RunList(&Events, EventWrite); /* because we keep this in a linked list */
  1335.   printf("writeSysTab = %d\n", writeSysTab());
  1336.  
  1337.   }
  1338. /*
  1339. * zapLogFile()
  1340. *
  1341. * This erases & re-initializes ctdllog.sys.
  1342. */
  1343. char zapLogFile()
  1344.   {
  1345.   int  i;
  1346.   char cx;
  1347.   if (!FirstInit)
  1348.     {
  1349.     printf("\nWipe out log file? ");
  1350.     cx = simpleGetch();
  1351.     if (toUpper(cx) != 'Y')   return FALSE;
  1352.     printf("\n");
  1353.  
  1354.     }
  1355.   /* clear RAM buffer out:      */
  1356.   logBuf.lbflags.L_INUSE = FALSE;
  1357.   for (i = 0;  i < MAILSLOTS;  i++)
  1358.     {
  1359.     logBuf.lbMail[i].rbmsgLoc = 0l;
  1360.     logBuf.lbMail[i].rbmsgNo  = 0l;
  1361.  
  1362.     }
  1363.   for (i = 0;  i < NAMESIZE;  i++)
  1364.     {
  1365.     logBuf.lbname[i] = 0;
  1366.     logBuf.lbpw[i]   = 0;
  1367.  
  1368.     }
  1369.   /* write empty buffer all over file;  */
  1370.   for (i = 0; i < cfg.MAXLOGTAB;  i++)
  1371.     {
  1372.     printf("Clearing log #%d\r", i);
  1373.     putLog(&logBuf, i);
  1374.     logTab[i].ltnewest = logBuf.lbvisit[0];
  1375.     logTab[i].ltlogSlot= i;
  1376.     logTab[i].ltnmhash = hash(logBuf.lbname);
  1377.     logTab[i].ltpwhash = hash(logBuf.lbpw  );
  1378.  
  1379.     }
  1380.   return TRUE;
  1381.  
  1382.   }
  1383. /*
  1384. * netInit()
  1385. *
  1386. * This will Initialize RAM index for Ctdlnet.sys.
  1387. */
  1388. void netInit()
  1389.   {
  1390.   label temp;
  1391.   int i = 0;
  1392.   long length;
  1393.   if (!cfg.BoolFlags.netParticipant) return;
  1394.   totalBytes(&length, netfl);
  1395.   cfg.netSize = (int) (length / NB_TOTAL_SIZE);
  1396.   if (cfg.netSize)
  1397.   netTab = (NetTable *) GetDynamic(sizeof (*netTab) * cfg.netSize);
  1398.   else
  1399.   netTab = NULL;
  1400.   while (i < cfg.netSize)
  1401.     {
  1402.     getNet(i, &netBuf);
  1403.     netTab[i].netTRooms = (SharedRoom *)
  1404.     GetDynamic(sizeof (*netBuf.netRooms) * SHARED_ROOMS);
  1405.     normId(netBuf.netId, temp);
  1406.     netTab[i].ntnmhash = hash(netBuf.netName);
  1407.     netTab[i].ntidhash = hash(temp);
  1408.     strCpy(netTab[i].ntShort, netBuf.nbShort);
  1409.     copy_struct(netBuf.nbflags, netTab[i].ntflags);
  1410.     movmem(netBuf.netRooms, netTab[i].netTRooms,
  1411.     sizeof *netBuf.netRooms * SHARED_ROOMS);
  1412.     netTab[i].ntMemberNets = netBuf.MemberNets;
  1413.     printf("System %3d. %s\n", i,
  1414.     (netBuf.nbflags.in_use) ? netBuf.netName : "<not in use>");
  1415.     i++;
  1416.  
  1417.     }
  1418.   if (cfg.MailHub != 0)
  1419.     {
  1420.     if (searchNameNet(cfg.MailHub + cfg.codeBuf, &netBuf) == -1)
  1421.     illegal("Your #MailHub node was not found in your CtdlNet.Sys.");
  1422.     if (netBuf.nbRoute != -1 &&
  1423.     netTab[netBuf.nbRoute].ntGen == netBuf.nbRouteGen)
  1424.     illegal("You must have a direct connect to your #MailHub.");
  1425.  
  1426.     }
  1427.  
  1428.   }
  1429. /*
  1430. * strCmpU()
  1431. *
  1432. * This is strcmp(), but ignoring case distinctions.  Found in most C libraries
  1433. * as stricmp().  Someday we should switch over.
  1434. */
  1435. int strCmpU(char s[], char t[])
  1436.   {
  1437.   int  i;
  1438.   i = 0;
  1439.   while (toUpper(s[i]) == toUpper(t[i]))
  1440.     {
  1441.     if (s[i++] == '\0')  return SAMESTRING ;
  1442.  
  1443.     }
  1444.   return  toUpper(s[i]) - toUpper(t[i]);
  1445.  
  1446.   }
  1447. /*
  1448. * crashout()
  1449. *
  1450. * This handles a fatal error, for library functions.
  1451. */
  1452. void crashout(char *str)
  1453.   {
  1454.   illegal(str);
  1455.  
  1456.   }
  1457. /*
  1458. * cfindMessage()
  1459. *
  1460. * This function gets all set up to do something with a message.
  1461. */
  1462. char cfindMessage(SECTOR_ID loc, MSG_NUMBER id)
  1463.   {
  1464.   long atol();
  1465.   MSG_NUMBER here;
  1466.   extern struct mBuf mFile1;
  1467.   startAt(msgfl, &mFile1, loc, 0);
  1468.   do
  1469.     {
  1470.     getMessage(getMsgChar, FALSE, FALSE, TRUE);
  1471.     here = atol(msgBuf.mbId);
  1472.  
  1473.     }
  1474.   while (here != id &&  mFile1.thisSector == loc);
  1475.   return (char)((here == id));
  1476.  
  1477.   }
  1478. /*
  1479. * CheckFloors()
  1480. *
  1481. * This function will check the floors.
  1482. */
  1483. void CheckFloors()
  1484.   {
  1485.   SYS_FILE     tempName;
  1486.   FILE   *flrfl;
  1487.   struct floor FloorBuf;
  1488.   struct floor *fptr;
  1489.   extern char  *R_W_ANY, *WRITE_ANY;
  1490.   int rover, cindex;
  1491.   int flag;
  1492.   char *cptr;
  1493.  
  1494.   makeSysName(tempName, "ctdlflr.sys", &cfg.floorArea);
  1495.  
  1496.   if ((flrfl = fopen(tempName, R_W_ANY)) == NULL)
  1497.     {
  1498.     printf(" %s not found, creating new file.\n", tempName);
  1499.     if ((flrfl = fopen(tempName, WRITE_ANY)) == NULL)
  1500.     illegal("?Can't create the floor file!");
  1501.  
  1502.     }
  1503.   /** create initial floor entry **/
  1504.   strCpy(FloorBuf.FlName, cfg.codeBuf + cfg.MainFloor);
  1505.   FloorBuf.FlInuse = TRUE;
  1506.   memset(FloorBuf.FlModerator, '\0',sizeof(label));
  1507.   /** write floor creation entry **/
  1508.   if( fwrite(&FloorBuf, sizeof FloorBuf, 1, flrfl) != 1)
  1509.     {
  1510.     printf("Write Error: %s\n",tempName);
  1511.     };
  1512.   totalBytes(&FloorSize, flrfl);
  1513.   FloorSize /= sizeof FloorBuf;
  1514.   printf("Current Floor file size is %ld entries\n",FloorSize);
  1515.   fclose(flrfl);
  1516.   /*  strip unused records  */
  1517.   if ((flrfl = fopen(tempName, READ_ANY)) == NULL)
  1518.     {
  1519.     illegal("?Can't read the floor file!");
  1520.     };
  1521.   fptr = (struct floor *)malloc(FloorSize * sizeof(struct floor) );
  1522.   /* get buffer for whole file */
  1523.   if( fptr == NULL )
  1524.     {
  1525.     free(fptr);
  1526.     illegal(" cannot allocate memory for a floor file!");
  1527.     };
  1528.   /* read whole file */
  1529.   if( fread( fptr, sizeof(struct floor), FloorSize, flrfl) != FloorSize )
  1530.     {
  1531.     free(fptr);
  1532.     illegal("Unable to read floor file!");
  1533.     };
  1534.   fclose(flrfl);
  1535.   /* Now, we know that there is at least one good record so we
  1536.      check from the end until we find a record in use
  1537.   */
  1538.   flag = TRUE;
  1539.   for( rover = 0; rover < FloorSize && fptr[rover].FlInuse  == TRUE; rover++)
  1540.     {
  1541.     /* validate that the Name are alpha characters and
  1542.        printable. Also test to see if In use.
  1543.     */
  1544.     cptr = &fptr[rover].FlModerator[0];
  1545.     if( ( *cptr >= 'a' && *cptr <= 'z' ) || ( *cptr >= 'A' && *cptr <= 'Z' ) )
  1546.       {
  1547.       printf("%20s is moderator for %s\n",fptr[rover].FlModerator,fptr[rover].FlName);
  1548.       }
  1549.     else
  1550.       {
  1551.       for( cindex = 0; cindex <20 ; cindex++)
  1552.         {
  1553.         cptr[cindex] = '\0';
  1554.         };
  1555.       };
  1556.     };
  1557.   FloorSize = rover;
  1558.   printf("New Floor file size is %ld entries\n",FloorSize);
  1559.   if ((flrfl = fopen(tempName, W_R_ANY)) == NULL)
  1560.     {
  1561.     free(fptr);
  1562.     illegal("?Can't Open the floor file to re-write!");
  1563.     };
  1564.   if( fwrite(fptr, sizeof(struct floor), FloorSize, flrfl) != FloorSize)
  1565.     {
  1566.     printf("Write Error: %s\n",tempName);
  1567.     };
  1568.   free(fptr);
  1569.   fclose(flrfl);
  1570.   }
  1571. /*
  1572. * CheckNet()
  1573. *
  1574. * This creates the Ctdlnet.sys if needed.
  1575. */
  1576. void CheckNet()
  1577.   {
  1578.   SYS_FILE      tempName;
  1579.   makeSysName(tempName, "ctdlnet.sys", &cfg.netArea);
  1580.   if ((netfl = fopen(tempName, READ_ANY)) == NULL)
  1581.     {
  1582.     printf(" %s not found, creating new file.\n", tempName);
  1583.     if ((netfl = fopen(tempName, WRITE_ANY)) == NULL)
  1584.     illegal("?Can't create the net file!");
  1585.  
  1586.     }
  1587.  
  1588.   }
  1589. /*
  1590. * NetParse()
  1591. *
  1592. * This function is responsible for parsing the network parameters.
  1593. */
  1594. static char NetParse(char *line, int *offset, char *var, int arg, int SetVal)
  1595.   {
  1596.   char temp[100];
  1597.   if (strCmpU(var, "#NewNetPrivs")    == SAMESTRING)
  1598.     {
  1599.     cfg.BoolFlags.NetDft      = arg;
  1600.     return TRUE;
  1601.  
  1602.     }
  1603.   else if (strCmpU(var, "#RouteMail")     == SAMESTRING)
  1604.     {
  1605.     cfg.BoolFlags.RouteMail = arg;
  1606.     return TRUE;
  1607.  
  1608.     }
  1609.   else if (strCmpU(var, "#SCAN-NET-MESSAGES") == SAMESTRING)
  1610.     {
  1611.     cfg.BoolFlags.NetScanBad = TRUE;
  1612.     return TRUE;
  1613.  
  1614.     }
  1615.   else if (strCmpU(var, "#SHARED-ROOMS")  == SAMESTRING)
  1616.     {
  1617.     if (SetVal)
  1618.       {
  1619.       if (SHARED_ROOMS != arg && cfg.netSize != 0)
  1620.       illegal(
  1621.       "SHARED-ROOMS parameter does not equal old value!");
  1622.       else
  1623.       SHARED_ROOMS = arg;
  1624.  
  1625.       }
  1626.     else
  1627.       {
  1628.       SHARED_ROOMS = arg;
  1629.  
  1630.       }
  1631.     return TRUE;
  1632.  
  1633.     }
  1634.   else if (strCmpU(var, "#NETWORK"   )    == SAMESTRING)
  1635.     {
  1636.     cfg.BoolFlags.netParticipant = arg;
  1637.     return TRUE;
  1638.     #ifdef NEED_LONGHAUL
  1639.  
  1640.     }
  1641.   else if (strCmpU(var, "#LONG-HAUL" )    == SAMESTRING)
  1642.     {
  1643.     cfg.BoolFlags.longHaul = arg;
  1644.     return TRUE;
  1645.     #endif
  1646.  
  1647.     }
  1648.   else if (strCmpU(var, "#NET_AREA_SIZE") == SAMESTRING)
  1649.     {
  1650.     cfg.sizeArea = arg;
  1651.     return TRUE;
  1652.  
  1653.     }
  1654.   else if (strCmpU(var, "#MAX_NET_FILE")    == SAMESTRING)
  1655.     {
  1656.     cfg.maxFileSize = arg;
  1657.     return TRUE;
  1658.  
  1659.     }
  1660.   else if (strCmpU(var, "#callOutSuffix") == SAMESTRING)
  1661.     {
  1662.     readString(line, &cfg.codeBuf[*offset], TRUE);
  1663.     cfg.netSuffix = *offset;
  1664.     while (cfg.codeBuf[*offset])
  1665.     (*offset)++;
  1666.     (*offset)++;
  1667.     return TRUE;
  1668.  
  1669.     }
  1670.   else if (strCmpU(var, "#callOutPrefix") == SAMESTRING)
  1671.     {
  1672.     readString(line, &cfg.codeBuf[*offset], TRUE);
  1673.     DefaultPrefix = *offset;
  1674.     while (cfg.codeBuf[*offset])
  1675.     (*offset)++;
  1676.     (*offset)++;
  1677.     return TRUE;
  1678.  
  1679.     }
  1680.   else if (strCmpU(var, "#DialOut300") == SAMESTRING)
  1681.     {
  1682.     readString(line, &cfg.codeBuf[*offset], TRUE);
  1683.     cfg.DialPrefixes[ONLY_300] = *offset;
  1684.     while (cfg.codeBuf[*offset])
  1685.     (*offset)++;
  1686.     (*offset)++;
  1687.     return TRUE;
  1688.  
  1689.     }
  1690.   else if (strCmpU(var, "#DialOut1200") == SAMESTRING)
  1691.     {
  1692.     readString(line, &cfg.codeBuf[*offset], TRUE);
  1693.     cfg.DialPrefixes[BOTH_300_1200] = *offset;
  1694.     while (cfg.codeBuf[*offset])
  1695.     (*offset)++;
  1696.     (*offset)++;
  1697.     return TRUE;
  1698.  
  1699.     }
  1700.   else if (strCmpU(var, "#DialOut2400") == SAMESTRING)
  1701.     {
  1702.     readString(line, &cfg.codeBuf[*offset], TRUE);
  1703.     cfg.DialPrefixes[TH_3_12_24] = *offset;
  1704.     while (cfg.codeBuf[*offset])
  1705.     (*offset)++;
  1706.     (*offset)++;
  1707.     return TRUE;
  1708.  
  1709.     }
  1710.   else if (strCmpU(var, "#DialOut4800") == SAMESTRING)
  1711.     {
  1712.     readString(line, &cfg.codeBuf[*offset], TRUE);
  1713.     cfg.DialPrefixes[B_4] = *offset;
  1714.     while (cfg.codeBuf[*offset])
  1715.     (*offset)++;
  1716.     (*offset)++;
  1717.     return TRUE;
  1718.  
  1719.     }
  1720.   else if (strCmpU(var, "#DialOut9600") == SAMESTRING)
  1721.     {
  1722.     readString(line, &cfg.codeBuf[*offset], TRUE);
  1723.     cfg.DialPrefixes[B_5] = *offset;
  1724.     while (cfg.codeBuf[*offset])
  1725.     (*offset)++;
  1726.     (*offset)++;
  1727.     return TRUE;
  1728.  
  1729.     }
  1730.   else if (strCmpU(var, "#DialOut14400") == SAMESTRING)
  1731.     {
  1732.     readString(line, &cfg.codeBuf[*offset], TRUE);
  1733.     cfg.DialPrefixes[B_6] = *offset;
  1734.     while (cfg.codeBuf[*offset])
  1735.     (*offset)++;
  1736.     (*offset)++;
  1737.     return TRUE;
  1738.  
  1739.     }
  1740.   else if (strCmpU(var, "#DialOut19200") == SAMESTRING)
  1741.     {
  1742.     readString(line, &cfg.codeBuf[*offset], TRUE);
  1743.     cfg.DialPrefixes[B_7] = *offset;
  1744.     while (cfg.codeBuf[*offset])
  1745.     (*offset)++;
  1746.     (*offset)++;
  1747.     return TRUE;
  1748.  
  1749.     }
  1750.   else if (strCmpU(var, "#nodeName" ) == SAMESTRING)
  1751.     {
  1752.     readString(line, &cfg.codeBuf[*offset], FALSE);
  1753.     NormStr(&cfg.codeBuf[*offset]);
  1754.     if (strLen(&cfg.codeBuf[*offset]) > 19)
  1755.     illegal("nodeName too long; must be less than 20");
  1756.     if (strchr(&cfg.codeBuf[*offset], '_') != NULL ||
  1757.     strchr(&cfg.codeBuf[*offset], '.') != NULL)
  1758.     illegal("The characters '.' and '_' are illegal in node names!");
  1759.     cfg.nodeName    = *offset;
  1760.     while (cfg.codeBuf[*offset]) /* step over string     */
  1761.     (*offset)++;
  1762.     (*offset)++;
  1763.     return TRUE;
  1764.  
  1765.     }
  1766.   else if (strCmpU(var, "#nodeId"   ) == SAMESTRING)
  1767.     {
  1768.     readString(line, &cfg.codeBuf[*offset], FALSE);
  1769.     if (strLen(&cfg.codeBuf[*offset]) > 19)
  1770.     illegal("nodeId too long; must be less than 20");
  1771.     cfg.nodeId      = *offset;
  1772.     while (cfg.codeBuf[*offset]) /* step over string     */
  1773.     (*offset)++;
  1774.     (*offset)++;
  1775.     return TRUE;
  1776.  
  1777.     }
  1778.   else if (strCmpU(var, "#MailHub"  ) == SAMESTRING)
  1779.     {
  1780.     readString(line, &cfg.codeBuf[*offset], FALSE);
  1781.     if (strLen(&cfg.codeBuf[*offset]) > 19)
  1782.     illegal("MailHub too long; must be less than 20");
  1783.     cfg.MailHub      = *offset;
  1784.     while (cfg.codeBuf[*offset]) /* step over string     */
  1785.     (*offset)++;
  1786.     (*offset)++;
  1787.     return TRUE;
  1788.  
  1789.     }
  1790.   else if (strCmpU(var, "#DomainDisplay") == SAMESTRING)
  1791.     {
  1792.     readString(line, cfg.DomainDisplay, FALSE);
  1793.     if (strLen(cfg.DomainDisplay) >= sizeof cfg.DomainDisplay)
  1794.     illegal("DomainDisplay is too long, must be less than 11");
  1795.     return TRUE;
  1796.  
  1797.     }
  1798.   else if (strCmpU(var, "#nodeDomain") == SAMESTRING)
  1799.     {
  1800.     readString(line, &cfg.codeBuf[*offset], FALSE);
  1801.     if (strLen(&cfg.codeBuf[*offset]) > 19)
  1802.     illegal("nodeDomain too long; must be less than 20");
  1803.     if (strchr(cfg.codeBuf + *offset, '_') != NULL ||
  1804.     strchr(cfg.codeBuf + *offset, '.') != NULL)
  1805.     illegal("Domain names cannot have '_' or '.' in them.");
  1806.     cfg.nodeDomain = *offset;
  1807.     while (cfg.codeBuf[*offset]) /* step over string     */
  1808.     (*offset)++;
  1809.     (*offset)++;
  1810.     return TRUE;
  1811.  
  1812.     }
  1813.   else if (strCmpU(var, "#ServeDomain") == SAMESTRING)
  1814.     {
  1815.     readString(line, temp, FALSE);
  1816.     if (strLen(temp) > 19)
  1817.     illegal("ServeDomain value is too long, must be less than 19 characters.");
  1818.     AddData(&Serves, strdup(temp), NULL, FALSE);
  1819.     cfg.DomainHandlers++;
  1820.     return TRUE;
  1821.  
  1822.     }
  1823.   return FALSE;
  1824.  
  1825.   }
  1826.  
  1827. void  Zap_Nodes_Message_Index()  /* zap last netted message */
  1828.   {
  1829.   int node, slot;
  1830.   for(node = 0; node < cfg.netSize; node++)
  1831.     {
  1832.     if( !netTab[node].ntflags.in_use )continue;
  1833.     getNet(node,&netBuf);
  1834.     for( slot=0; slot < SHARED_ROOMS; slot++)
  1835.       {
  1836.       if( !roomTab[netTabRoomSlot(node, slot)].rtflags.SHARED)continue;
  1837.       netTab[node].netTRooms[slot].lastMess = 0;
  1838.       netBuf.netRooms[slot].lastMess = 0;
  1839.       };
  1840.     putNet(node,&netBuf);
  1841.     };
  1842.  
  1843.   }
  1844.